// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
import RecycleListItem from "./RecycleListItem";
import RecycleListLayout from "./RecycleListLayout";

const { ccclass, property, requireComponent } = cc._decorator;

@ccclass
@requireComponent(cc.ScrollView)
export default class RecycleList extends cc.Component {
    @property(cc.Node)
    itemNode: cc.Node = null;

    @property(cc.Prefab)
    itemPrefab: cc.Prefab = null;

    @property
    frameLoad: boolean = false;

    @property
    frameLoadCount: number = 1;

    @property
    filterAnimate: boolean = false;


    get data(): Array<any> {
        return this._tempDatas || this._data;
    }

    set data(value: Array<any>) {
        this._data = value || [];
        this.updateData();
    }

    public tempNode: cc.Node = null;

    public scrollView: cc.ScrollView = null;
    public content: cc.Node = null;
    public view: cc.Node = null;

    private _data: Array<any> = [];
    private _tempDatas: Array<any> = null;
    private _recycleListLayout: RecycleListLayout = null;
    private _itmePool: cc.Node[] = [];
    private _items: Array<RecycleListItem> = null;
    private _itmesState: Map<number, boolean> = null;

    onLoad() {
        this.scrollView = this.node.getComponent(cc.ScrollView);
        this.content = this.scrollView.content;
        this.view = this.content.parent;
        this._recycleListLayout = this.content.getComponent(RecycleListLayout);
        this._recycleListLayout.recycleList = this;

        if (this.itemNode) this.itemNode.removeFromParent();
        this.tempNode = this.itemNode || (this.itemPrefab ? cc.instantiate(this.itemPrefab) : null);
        this._items = new Array();
        this._itmesState = new Map();

        this.content.on(cc.Node.EventType.POSITION_CHANGED, this._recycleListLayout.onContentPositionChanged, this._recycleListLayout);
        this.view.on(cc.Node.EventType.SIZE_CHANGED, this.updateData, this);

        this.updateData();
    }

    onDestroy() {
        this.content.off(cc.Node.EventType.POSITION_CHANGED, this._recycleListLayout.onContentPositionChanged, this._recycleListLayout);
        this.view.off(cc.Node.EventType.SIZE_CHANGED, this.updateData, this);

        for (let v of this._itmePool) {
            v.destroy();
        }
    }

    protected lateUpdate(dt: number): void {
        this._recycleListLayout.updateLayout();
    }

    /**
     * 滚动到指定下标
     * @param dataIndex 
     * @param time 
     * @param percentX rect布局:视图水平方向百分比位置  bezier布局：路径百分比位置
     * @param percentY rect布局:视图垂直方向百分位置
     */
    public scrollToIndex(dataIndex: number, time: number = 0.3, percentX: number = 0, percentY: number = 1) {
        percentX = Math.max(Math.min(percentX, 1), 0);
        percentY = Math.max(Math.min(percentY, 1), 0);
        this.scrollView.scrollToOffset(this._recycleListLayout.getScrollOffset(dataIndex, percentX, percentY), time, true);
    }

    /**
     * 
     * @param itemComp 
     * @param newDataIndex 
     */
    public itemDataChanged(itemComp: RecycleListItem, newDataIndex: number) {
        itemComp.dataIndex = newDataIndex;
        itemComp.setPosition(this._recycleListLayout.getItemPositionByDataIndex(itemComp.dataIndex));
        if (this.getData(itemComp.dataIndex) !== undefined) {
            itemComp.show();
            itemComp.data = this.getData(itemComp.dataIndex);
            itemComp.refresh();
        } else {
            itemComp.data = null;
            itemComp.hide();
        }
    }

    private updateData() {
        if (!(this.data || this._tempDatas) || !this.scrollView) return;
        this.scrollView.stopAutoScroll();
        this._itmePool.push(...Array.from(this.content.children));
        this.content.removeAllChildren();
        this._items.length = 0;
        this._recycleListLayout.resetLayout();
    }

    public loadItem(itemIndex: number): RecycleListItem {
        let itemComp: RecycleListItem;
        if (!this._items[itemIndex]) {
            let node = this._itmePool.pop() || cc.instantiate(this.tempNode);
            this._items[itemIndex] = itemComp = node.getComponent(RecycleListItem);
            this._items[itemIndex].node.parent = this.content;
            itemComp.itemIndex = itemIndex;
            itemComp.dataIndex = itemComp.dataIndex = -1;
        } else {
            itemComp = this._items[itemIndex];
        }
        return itemComp;
    }

    public getDataLength(): number {
        let data = this._tempDatas || this._data;
        return data ? data.length : 0;
    }

    public getData(index: number): any {
        let data = this._tempDatas || this._data;
        return data && data[index];
    }

    public getItems(): Array<RecycleListItem> {
        return this._items;
    }
    // public addItem(data: any) {

    // }

    // public removeItem(index: number) {

    // }

    // public refreshItem(index: number) {

    // }

    // public refresh() {
    //     let chidlren = this._content.children;
    //     let com: RecycleListItem;
    //     for (let v of chidlren) {
    //         com = v.getComponent(RecycleListItem);
    //         if (com) com.refresh();
    //     }
    // }
}